package math_generic;

public class Vector3 
{
	public float x;
	public float y;
	public float z;
	
	public Vector3(float x, float y, float z)
	{
		this.x = x;
		this.y = y;
		this.z = z;		
	}
	
	/* Calculates the magnitude of the vector */
	public float magnitude()
	{
		return (float) Math.sqrt(x*x + y*y + z*z);
	}
	
	public static float magnitude(float x, float y, float z)
	{
		return (float) Math.sqrt(x*x + y*y + z*z);
	}
	
	public static float magnitude(Vector3 vector)
	{
		return (float) Math.sqrt(vector.x*vector.x + vector.y*vector.y + vector.z*vector.z);
	}
	
	/* Returns a vector with direction = angle, and norm = scalar */
	public static Vector3 calculateResultant(float scalar, float angleHOR, float angleVERT, boolean inverted)
	{
		float x;
		float y;
		float z;
		
		/* When calculating lateral movement, sin and cos are inverted. See moveForward and moveRight in Camera.java */
		if(inverted)
		{
			x = (float) (scalar * Math.cos(angleHOR));
			z = -(float) (scalar * Math.sin(angleHOR));
		}
		else
		{
			x = (float) (scalar * Math.sin(angleHOR));
			z = (float) (scalar * Math.cos(angleHOR));
		}
		
		y = (float) (scalar * Math.sin(angleVERT));
		
		return new Vector3(x, y, z);
	}
	
	/* Normalized the vector components */
	public Vector3 normalize()
	{
		float mag = magnitude();
		return (new Vector3(x/mag, y/mag, z/mag)); 
	}
	
	/* Returns a vector with magnitude = K */
	public static Vector3 getVectorWithNorm(Vector3 vector, float K)
	{
		float magnitude = magnitude(vector);
		
		return new Vector3(K*vector.x/magnitude, 
				  		   K*vector.y/magnitude,
				  		   K*vector.z/magnitude);
	}
	
	/* Returns the unit vector of vector */
	public static Vector3 getUnitVector(Vector3 vector)
	{
		float magnitude = magnitude(vector);
		
		return new Vector3(vector.x/magnitude,
						   vector.y/magnitude,
						   vector.z/magnitude);
	}
	
	public static Vector3 normalize(Vector3 vector)
	{
		return getUnitVector(vector);
	}
	
	/* Returns the resultant vector due to the summation of this and other vector. 
	 * The resultant vector has magnitude of norm */
	public Vector3 add(Vector3 other)
	{
		return new Vector3(this.x + other.x,
						   this.y + other.y,
						   this.z + other.z);
	}
	
	public static Vector3 add(Vector3 v1, Vector3 v2)
	{
		return new Vector3(v1.x + v2.x,
						   v1.y + v2.y,
						   v1.z + v2.z);
	}
	
	public Vector3 scale(float k)
	{
		return (new Vector3(x*k, y*k, z*k));
	}
}
